#include<map>
#include<type_traits>
#include<functional>
#include<iterator>
#include<algorithm>
#include<string>
#include<iterator>
#include<iostream>

struct regexTRIM {};


template<typename SOURCEITER, typename VALUETYPE>
std::pair<SOURCEITER, SOURCEITER> trim(SOURCEITER iterBein, SOURCEITER iterEnd, VALUETYPE findValue)
{
	if constexpr (std::is_same<VALUETYPE, std::iterator_traits<SOURCEITER>::value_type>::value)
	{
		if ((iterBein = std::find_if(iterBein, iterEnd, std::bind(std::not_equal_to<>(), std::placeholders::_1, findValue))) != iterEnd)
			iterEnd = std::find_if(std::make_reverse_iterator(iterEnd), std::make_reverse_iterator(iterBein), std::bind(std::not_equal_to<>(), std::placeholders::_1, findValue)).base();
		return { iterBein,iterEnd };
	}
	return { iterBein,iterEnd };
}



template<typename SOURCEITER, typename TRIMFUNCTION>
std::pair<SOURCEITER, SOURCEITER> trim_if(SOURCEITER iterBein, SOURCEITER iterEnd, TRIMFUNCTION trimFun)
{
	if ((iterBein = std::find_if_not(iterBein, iterEnd, trimFun)) != iterEnd)
		iterEnd = std::find_if_not(std::make_reverse_iterator(iterEnd), std::make_reverse_iterator(iterBein), trimFun).base();
	return { iterBein,iterEnd };
}


//trim_if 类正则函数形式，TRIMFUNCTIONFRONT 要求正向检查返回trim后首位置，TRIMFUNCTIONBACK则为反向检查返回trim后尾位置

template<typename SOURCEITER, typename TRIMFUNCTIONFRONT, typename TRIMFUNCTIONBACK>
std::pair<SOURCEITER, SOURCEITER> trim_if(SOURCEITER iterBein, SOURCEITER iterEnd, TRIMFUNCTIONFRONT trimFunf, TRIMFUNCTIONBACK trimFunb)
{
	if ((iterBein = trimFunf(iterBein, iterEnd)) != iterEnd)
		iterEnd = trimFunb(iterBein, iterEnd);
	return { iterBein,iterEnd };
}



int main()
{
	std::string str{ " feewfwerfewrfg " };
	int num1{};
	std::pair<decltype(str)::const_iterator, decltype(str)::const_iterator>p1;
	p1 = trim(str.cbegin(), str.cend(), ' ');
	std::cout << "|";
	std::copy(p1.first, p1.second, std::ostream_iterator<char>(std::cout));
	std::cout << "|\n";

	p1 = trim_if(str.cbegin(), str.cend(), [](auto const ch) {return ch == ' '; });
	std::cout << "|";
	std::copy(p1.first, p1.second, std::ostream_iterator<char>(std::cout));
	std::cout << "|\n";

	const char *cstr{ "fabAewfwerfewRcfgh" };
	auto p2 = trim(cstr, cstr+strlen(cstr), 'f');
	std::cout << "|";
	std::copy(p2.first, p2.second, std::ostream_iterator<char>(std::cout));
	std::cout << "|\n";

	p2 = trim_if(cstr, cstr + strlen(cstr), [](auto const ch) {return islower(ch); });
	std::cout << "|";
	std::copy(p2.first, p2.second, std::ostream_iterator<char>(std::cout));
	std::cout << "|\n";

	str.assign("<><fin><test>fewfergr<234><5gtfrt><gdr/.hrthtr>");
	p1 = trim_if(str.cbegin(), str.cend(), 
		[](auto iterBegin, auto iterEnd)
	{
		while (iterBegin != iterEnd)
		{
			if (*iterBegin != '<')
				return iterBegin;
			if ((iterBegin = find(iterBegin+1, iterEnd, '>')) == iterEnd)
				return iterBegin;
			++iterBegin;
		}
		return iterBegin;
	},
		[](auto iterBegin, auto iterEnd)
	{
		auto iterFront{ std::make_reverse_iterator(iterEnd) }, iterBack{ std::make_reverse_iterator(iterBegin) };
		while (iterFront != iterBack)
		{
			if (*iterFront != '>')
				return iterFront.base();
			if ((iterFront = find(iterFront + 1, iterBack, '<')) == iterBack)
				return iterFront.base();
			++iterFront;
		}
		return iterFront.base();
	});
	std::cout << "|";
	std::copy(p1.first, p1.second, std::ostream_iterator<char>(std::cout));
	std::cout << "|\n";


    // 
	int arr[]{ 100,200,-5,-20,-30,-40,-50,-60,-70,-80,-90,1000,250,369,258,856,453,256,60,20,10,-10,-24 };
	std::pair<int*, int*>p3;
	p3= trim_if(std::begin(arr),std::end(arr),
		[](auto iterBegin,auto iterEnd)
	{
		int sum{};
		return (iterBegin = std::find_if(iterBegin, iterEnd, [&sum](auto const num)
		{
			return (sum += num) < 0;	
		}));

	},
		[](auto iterBegin, auto iterEnd)
	{
		int sum{};
		auto iterFront{ std::make_reverse_iterator(iterEnd) }, iterBack{ std::make_reverse_iterator(iterBegin) };
		return (iterFront = std::find_if(iterFront, iterBack, [&sum](auto const num)
		{
			return (sum += num) > 0;
		})).base();
	});
	std::cout << "|";
	std::copy(p3.first, p3.second, std::ostream_iterator<int>(std::cout," "));
	std::cout << "|\n";
    
	return 0;
}